<template>
  <NButton tag="div" v-bind="$attrs" @click="handleClick">
    <template #icon>
      <UploadIcon class="w-4 h-4" />
    </template>

    <span>
      <slot />
    </span>

    <input
      ref="inputRef"
      type="file"
      accept=".sql,.txt,application/sql,text/plain"
      class="hidden"
      @change="handleUpload"
    />
  </NButton>

  <FileContentPreviewModal
    v-if="selectedFile"
    :file="selectedFile"
    @cancel="cleanup"
    @confirm="handleStatementConfirm"
  />
</template>

<script lang="ts" setup>
import { UploadIcon } from "lucide-vue-next";
import { NButton } from "naive-ui";
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import FileContentPreviewModal from "@/components/FileContentPreviewModal.vue";
import { pushNotification } from "@/store";
import { MAX_UPLOAD_FILE_SIZE_MB } from "@/utils";

const emit = defineEmits<{
  (event: "update:sql", text: string, filename: string): void;
}>();

const { t } = useI18n();
const inputRef = ref<HTMLInputElement>();
const selectedFile = ref<File | null>(null);

const handleClick = () => {
  inputRef.value?.click();
};

const cleanup = () => {
  selectedFile.value = null;
  if (!inputRef.value) {
    return;
  }
  inputRef.value.files = null;
  inputRef.value.value = "";
};

const handleUpload = async (e: Event) => {
  const target = e.target as HTMLInputElement;
  const file = (target.files || [])[0];
  const cleanup = () => {
    // Note that once selected a file, selecting the same file again will not
    // trigger <input type="file">'s change event.
    // So we need to do some cleanup stuff here.
    target.files = null;
    target.value = "";
  };

  if (!file) {
    return cleanup();
  }
  if (file.size > MAX_UPLOAD_FILE_SIZE_MB * 1024 * 1024) {
    pushNotification({
      module: "bytebase",
      style: "CRITICAL",
      title: t("issue.upload-sql-file-max-size-exceeded", {
        size: `${MAX_UPLOAD_FILE_SIZE_MB}MB`,
      }),
    });
    return cleanup();
  }

  selectedFile.value = file;

  cleanup();
};

const handleStatementConfirm = (statement: string) => {
  emit("update:sql", statement, selectedFile.value!.name);
  cleanup();
};
</script>
